import org.junit.Test;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.highgui.HighGui;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.util.List;

public class HistogramFaceRecognition {

    static JLabel imageView;

    public static Mat norm_0_255(Mat src) {
        Mat dst = new Mat();
        switch (src.channels()) {
            case 1:
                Core.normalize(src, dst, 0, 255, Core.NORM_MINMAX, CvType.CV_8UC1);
                break;
            case 3:
                Core.normalize(src, dst, 0, 255, Core.NORM_MINMAX, CvType.CV_8UC3);
                break;
            default:
                src.copyTo(dst);
                break;
        }
        return dst;
    }

    public static void read_csv(final String filename, List<Mat> images, List<Integer> labels, char separator) throws Exception {
        if (filename.isEmpty()) {
            throw new Exception("没有提供有效的输入文件, 请检查给定的文件名");
        }
        String line, path, classLabel;
        //while()
    }

    public void detectHumenSmile(Mat rgb, Mat gray) {

        String resourcePath = this.getClass().getResource("haarcascade_smile.xml").getPath().substring(1);
        CascadeClassifier cascade = new CascadeClassifier(resourcePath);

        if (cascade.empty()) {
            System.out.println("文件读取失败");
            return;
        }
        MatOfRect rect = new MatOfRect();
        cascade.detectMultiScale(gray, rect);
        for (Rect re : rect.toArray()) {

           /* Imgproc.rectangle(rgb, new Point(re.x, re.y), new Point(re.x
                    + re.width, re.y + re.height), new Scalar(0, 255, 0));*/
            Imgproc.circle(rgb,new Point(re.x+re.width*0.5,re.y+re.height*0.5),(re.width+re.height)/4,new Scalar(0,255,0));
        }

        HighGui.imshow("ImageShow", rgb);
    }

    public void detectHumenFrontEye(Mat rgb, Mat gray) {

        String resourcePath = this.getClass().getResource("haarcascade_eye.xml").getPath().substring(1);
        CascadeClassifier cascade = new CascadeClassifier(resourcePath);

        if (cascade.empty()) {
            System.out.println("文件读取失败");
            return;
        }
        MatOfRect rect = new MatOfRect();
        cascade.detectMultiScale(gray, rect);
        for (Rect re : rect.toArray()) {

           /* Imgproc.rectangle(rgb, new Point(re.x, re.y), new Point(re.x
                    + re.width, re.y + re.height), new Scalar(0, 255, 0));*/
            Imgproc.circle(rgb,new Point(re.x+re.width*0.5,re.y+re.height*0.5),(re.width+re.height)/4,new Scalar(0,255,0));
        }

        HighGui.imshow("ImageShow", rgb);
    }

    public void detectHumenFrontFace(Mat rgb, Mat gray) {

        String resourcePath = this.getClass().getResource("lbpcascade_frontalface.xml").getPath().substring(1);
        CascadeClassifier cascade = new CascadeClassifier(resourcePath);

        if (cascade.empty()) {
            System.out.println("文件读取失败");
            return;
        }
        MatOfRect rect = new MatOfRect();
        cascade.detectMultiScale(gray, rect);
        for (Rect re : rect.toArray()) {

           /* Imgproc.rectangle(rgb, new Point(re.x, re.y), new Point(re.x
                    + re.width, re.y + re.height), new Scalar(0, 255, 0));*/
            Imgproc.circle(rgb,new Point(re.x+re.width*0.5,re.y+re.height*0.5),(re.width+re.height)/4,new Scalar(0,255,0));
        }

        HighGui.imshow("ImageShow", rgb);
    }

    @Test
    public void test() {

        System.setProperty("java.awt.headless", "false");
        System.load(this.getClass().getClassLoader().getResource("opencv_java451.dll").getPath());
        //System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        VideoCapture videoCapture = new VideoCapture();
        if (!videoCapture.open(0)) {
            System.out.println("相机打开失败");
            return;
        }
        while (true) {
            Mat img = new Mat();
            if (!videoCapture.read(img)) {
                return;
            }

            Mat rgb = new Mat();
            Imgproc.cvtColor(img, rgb, Imgproc.COLOR_BGR2RGB);
            Mat gray = new Mat();
            Imgproc.cvtColor(rgb, gray, Imgproc.COLOR_RGB2GRAY);
            //detectHumenFrontFace(img, gray);
            //detectHumenFrontEye(img,gray);
            detectHumenSmile(img,gray);

            //HighGui.imshow("ImageShow", rgb);
            HighGui.waitKey(10);
        }
    }

    private static Image toBufferedImage(Mat matrix,int x, int y, int width, int height, int mosaicSize) {

        int type = BufferedImage.TYPE_BYTE_GRAY;
        if (matrix.channels() > 1) {
            type = BufferedImage.TYPE_3BYTE_BGR;
        }
        int bufferSize = matrix.channels() * matrix.cols() * matrix.rows();
        byte[] buffer = new byte[bufferSize];
        matrix.get(0, 0, buffer);
        // 获取所有的像素点
        BufferedImage image = new BufferedImage(matrix.cols(), matrix.rows(), type);
        BufferedImage spinImage = new BufferedImage(image.getWidth(),
                image.getHeight(), image.TYPE_INT_RGB);
        if (image.getWidth() < mosaicSize || image.getHeight() < mosaicSize || mosaicSize <= 0) { // 马赛克格尺寸太大或太小
            System.err.println("马赛克尺寸设置不正确");
        }

        //2. 设置各方向绘制的马赛克块个数
        int xcount = 0; // 方向绘制个数
        int ycount = 0; // y方向绘制个数
        if (width % mosaicSize == 0) {
            xcount = width / mosaicSize;
        } else {
            xcount = width / mosaicSize + 1;
        }
        if (height % mosaicSize == 0) {
            ycount = height / mosaicSize;
        } else {
            ycount = height / mosaicSize + 1;
        }

        //3. 绘制马赛克(绘制矩形并填充颜色)
        Graphics gs = spinImage.getGraphics();
        gs.drawImage(image, 0, 0, null);
        int xTmp = x;
        int yTmp = y;
        for (int i = 0; i < xcount; i++) {
            for (int j = 0; j < ycount; j++) {
                //马赛克矩形格大小
                int mwidth = mosaicSize;
                int mheight = mosaicSize;
                if(i == xcount - 1){   //横向最后一个比较特殊，可能不够一个size
                    mwidth = width - xTmp;
                }
                if(j == ycount - 1){  //同理
                    mheight = height - yTmp;
                }
                //矩形颜色取中心像素点RGB值
                int centerX = xTmp;
                int centerY = yTmp;
                if (mwidth % 2 == 0) {
                    centerX += mwidth / 2;
                } else {
                    centerX += (mwidth - 1) / 2;
                }
                if (mheight % 2 == 0) {
                    centerY += mheight / 2;
                } else {
                    centerY += (mheight - 1) / 2;
                }
                Color color = new Color(image.getRGB(centerX, centerY));
                gs.setColor(color);
                gs.fillRect(xTmp, yTmp, mwidth, mheight);
                yTmp = yTmp + mosaicSize;// 计算下一个矩形的y坐标
            }
            yTmp = y;// 还原y坐标
            xTmp = xTmp + mosaicSize;// 计算x坐标
        }
        gs.dispose();

        final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
        System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);
        return image;
    }
    private static JFrame createJFrame(int width, int height) {
        JFrame frame = new JFrame();
        imageView = new JLabel();
        final JScrollPane imageScrollPane = new JScrollPane(imageView);
        imageScrollPane.setPreferredSize(new Dimension(width, height));
        frame.add(imageScrollPane, BorderLayout.CENTER);
        return frame;
    }



}